package com.h2.ref.server.web.social;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionData;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.ConnectionKey;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import com.h2.ref.server.user.model.User;

public class ConnectionRepositoryInMem {
   
   private ConnectionFactoryLocator _connectionRegistry;
   
   private Map<Integer, MultiValueMap<String, Connection<?>>> _connections;
   
   private Map<String, Integer> _users;
   
   ////
   ////
   
   public void init() {
      setConnections(
            new HashMap<Integer, MultiValueMap<String,Connection<?>>>());
      setUsers(new HashMap<String, Integer>());
   }
   
   private <A> String getProviderId(Class<A> apiType) {
      return getConnectionRegistry()
            .getConnectionFactory(apiType).getProviderId();
   }
   
   public MultiValueMap<String, Connection<?>> findAllConnections(User user) {
      return getConnections().get(user.getId());
   }
   
   public List<Connection<?>> findConnections(User user, String providerId) {
      if (getConnections().containsKey(user.getId())) {
         return getConnections().get(user.getId()).get(providerId);
      }
      return Collections.emptyList();
   }

   @SuppressWarnings("unchecked")
   public <A> List<Connection<A>> findConnections(User user, Class<A> apiType) {
      return (List<Connection<A>>)(List<?>)findConnections(user,
            getProviderId(apiType));
   }

   public MultiValueMap<String, Connection<?>> findConnectionsToUsers(User user,
         MultiValueMap<String, String> providerUserIds) {
      // TODO Auto-generated method stub
      return null;
   }

   public Connection<?> getConnection(User user, ConnectionKey connectionKey) {
      // TODO Auto-generated method stub
      return null;
   }

   public <A> Connection<A> getConnection(User user, Class<A> apiType,
         String providerUserId) {
      // TODO Auto-generated method stub
      return null;
   }

   public <A> Connection<A> getPrimaryConnection(User user, Class<A> apiType) {
      List<Connection<A>> connections = findConnections(user, apiType);
      if (connections != null && !connections.isEmpty()) {
         return connections.get(0);
      }
      return null;
   }

   public <A> Connection<A> findPrimaryConnection(User user, Class<A> apiType) {
      List<Connection<A>> connections = findConnections(user, apiType);
      if (connections != null && !connections.isEmpty()) {
         return connections.get(0);
      }
      return null;
   }

   public void addConnection(User user, Connection<?> connection) {
      if (getUsers().containsKey(connection.toString())) {
         //duplicate
         return;
      }
      
      //add connection
      ConnectionData data = connection.createData();
      List<Connection<?>> connections;
      MultiValueMap<String, Connection<?>> userConnections;
      if (getConnections().containsKey(user.getId())) {
         userConnections = getConnections().get(user.getId());
         connections = getConnections().get(user.getId()).get(data.getProviderId());
      }
      else {
         userConnections = new LinkedMultiValueMap<String, Connection<?>>();
         getConnections().put(user.getId(), userConnections);
         connections = new ArrayList<Connection<?>>();
         userConnections.put(data.getProviderId(), connections);
      }
      connections.add(connection);
      
      //add user
      getUsers().put(connection.getKey().toString(), user.getId());
   }

   public void updateConnection(User user, Connection<?> connection) {
      // TODO Auto-generated method stub
      
   }

   public void removeConnections(User user, String providerId) {
      if (getConnections().containsKey(user.getId())) {
         getConnections().get(user.getId()).remove(providerId);
      }
   }

   public void removeConnection(User user, ConnectionKey connectionKey) {
      if (getConnections().containsKey(user.getId())) {
         getConnections().get(user.getId()).remove(
               connectionKey.getProviderId());
      }
   }

   public Integer findUser(Connection<?> connection) {
      return getUsers().get(connection.getKey().toString());
   }

   /**
    * @return the connections
    */
   public Map<Integer, MultiValueMap<String, Connection<?>>> getConnections() {
      return _connections;
   }

   /**
    * @param connections the connections to set
    */
   public void setConnections(
         Map<Integer, MultiValueMap<String, Connection<?>>> connections) {
      _connections = connections;
   }

   /**
    * @return the connectionRegistry
    */
   public ConnectionFactoryLocator getConnectionRegistry() {
      return _connectionRegistry;
   }

   /**
    * @param connectionRegistry the connectionRegistry to set
    */
   public void setConnectionRegistry(ConnectionFactoryLocator connectionRegistry) {
      _connectionRegistry = connectionRegistry;
   }

   /**
    * @return the users
    */
   public Map<String, Integer> getUsers() {
      return _users;
   }

   /**
    * @param users the users to set
    */
   public void setUsers(Map<String, Integer> users) {
      _users = users;
   }

}
